package com.javastudy.jdkfeature.jdk7.file;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

/**
 * 下面例子是寻找某一目录下所有java源程序文件的代码,不会遍历目录的，只是当前目录查看
 */
public class FindingFilesInADirectory {
    public static void main(String[] args) throws Exception {
        Path path = Paths.get("E:\\OpenSources\\MyProjects\\eBilling");
        try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(path, "*.java")) {

            directoryStream.forEach(p -> System.out.println(p.getFileName()));

        } catch (IOException e) {
            e.printStackTrace();
        }

        Path dir = Paths.get("F:\\学习文档");
        List<Path> pathList = new ArrayList<>();
        try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
            for(Path e : stream){
                //System.out.println(e.toAbsolutePath());
                pathList.add(e.toAbsolutePath());
            }
        }catch(IOException e){

        }

        //listFiles(dir);
        countFileCounts1(pathList);
        countFileCounts2(pathList);
    }

    public static void listFiles(Path startingDir) throws IOException {
        long start = System.nanoTime();
//        Path startingDir = Paths.get("E:\\OpenSources\\MyProjects");
        List<Path> result = new LinkedList<Path>();
        Files.walkFileTree(startingDir, new FindJavaVisitor(result));
        System.out.println("1总数为：" + result.size()+"; time cost="+(System.nanoTime()-start));
    }

    //使用阻塞容器保存每次Executor处理的结果，在后面进行统一处理
    public static void countFileCounts1(List<Path> pathList) throws Exception{
        long start = System.nanoTime();
        ExecutorService exec = Executors.newCachedThreadPool();
        BlockingQueue<Future<Integer>> queue = new LinkedBlockingQueue<Future<Integer>>();
        for(Path path:pathList){
            Future<Integer> future =exec.submit(getFileCountsForADirectory(path));
            queue.add(future);
        }
        int sum = 0;
        int queueSize = queue.size();
        for(int i=0; i<queueSize; i++){
            sum += queue.take().get();
        }
        System.out.println("2总数为："+sum+"; time cost="+(System.nanoTime()-start));
        exec.shutdown();
    }

    //使用CompletionService(完成服务)保持Executor处理的结果
    public static void countFileCounts2(List<Path> pathList) throws InterruptedException, ExecutionException{
        long start = System.nanoTime();
        ExecutorService exec = Executors.newCachedThreadPool();
        CompletionService<Integer> execcomp = new ExecutorCompletionService<Integer>(exec);
        for(Path path:pathList){
            execcomp.submit(getFileCountsForADirectory(path));
        }
        int sum = 0;
        for(int i=0; i<pathList.size(); i++){
//检索并移除表示下一个已完成任务的 Future，如果目前不存在这样的任务，则等待。
            Future<Integer> future = execcomp.take();
            sum += future.get();
        }
        System.out.println("3总数为："+sum+"; time cost="+(System.nanoTime()-start));
        exec.shutdown();
    }

    //得到一个任务
    public static Callable<Integer> getFileCountsForADirectory(Path startingDir){
        final Random rand = new Random();
        Callable<Integer> task = new Callable<Integer>(){
            @Override
            public Integer call() throws Exception {
                List<Path> result = new LinkedList<Path>();
                Files.walkFileTree(startingDir, new FindJavaVisitor(result));
                return result.size();
            }
        };
        return task;
    }

    private static class FindJavaVisitor extends SimpleFileVisitor<Path> {
        private List<Path> result;
        public FindJavaVisitor(List<Path> result){
            this.result = result;
        }
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
            if(file.toString().endsWith(".pdf")){
                result.add(file.getFileName());
            }
            return FileVisitResult.CONTINUE;
        }
    }
}
